package com.juzhencms.apps.common.interceptor;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.juzhencms.apps.busi.entity.AdminLoginUser;
import com.juzhencms.apps.busi.service.AdminMenuService;
import com.juzhencms.apps.busi.service.CommonService;
import com.juzhencms.apps.busi.service.UserService;
import com.juzhencms.apps.base.common.config.Config;
import com.juzhencms.apps.base.common.database.DBTable;
import com.juzhencms.apps.base.common.util.DataLogUtil;
import com.juzhencms.apps.base.common.util.JWTUtil;
import com.juzhencms.apps.base.common.util.MD5Util;
import com.juzhencms.apps.base.common.util.WebUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class UserInterceptor implements HandlerInterceptor{

	
	@Autowired
    private CommonService commonService;
	
	@Autowired
	private DataLogUtil dataLog;
	
	@Autowired
    private AdminMenuService adminMenuService;
	
	@Autowired
	private UserService userService;
	
	/**
	 * 只能调用一次，在向客户端输出结果时使用
	 * @param string
	 * @param response
	 */
	private void writeToResponse(String string,HttpServletResponse response){
		OutputStreamWriter writer;
		try {
			writer = new OutputStreamWriter(response.getOutputStream(),"utf-8");
			response.setHeader("Content-type", "text/html;charset=UTF-8");   
			response.setCharacterEncoding("UTF-8");
			writer.write(string);
			writer.flush();
			dataLog.setResponse(string);
		} catch (IOException e) {
			log.error("输出报错", e);
		}
		
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// TODO Auto-generated method stub
		
		
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin,x-requested-with,Content-Type,Accept,app-token,app-time");
        response.setHeader("Access-Control-Allow-Credentials","true"); //是否支持cookie跨域
        response.setHeader("P3P","CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");//设置IE浏览器支持cookie跨域
        response.addHeader("X-Frame-Options","SAMEORIGIN");
        
    	if(handler.getClass().getSimpleName().equals("HandlerMethod")){
    		
        	HandlerMethod handlerMethod = (HandlerMethod) handler;
        	String controllerName=handlerMethod.getBean().getClass().getSimpleName();
        	String method=handlerMethod.getMethod().getName();
        	
        	
			//如果存在ehcache，将缓存重构的controllerName替换为之前的，避免权限校验出错
        	Matcher matcher = Pattern.compile("\\$\\$.+$").matcher(controllerName);
        	if(matcher.find()){
        		controllerName=matcher.replaceAll("");
        	}
        	log.info(controllerName+"."+method,this.getClass());
        	
        	//获取用户信息(包括权限数据),并将用户信息存入request
        	AdminLoginUser loginUser=userService.initLoginUserByCookie(request,response);
            
            
        	//记录访问日志,并对header中的参数进行简单验证
            if(!dataLog.initLog(handlerMethod)){
            	response.setStatus(403);
        	    response.getWriter().append("header error");
        	    return false;
            }
            
            
            
            //动态token校验，防止跨站伪造请求----------------------------------------------------------------
        	if(request.getParameter("data")!=null){
        		Map tokenResult=new HashMap();
        		tokenResult.put("result", -1);
        		tokenResult.put("msg", "验证失败，请刷新页面后重试");

        		String headerTime = request.getHeader("app-time");
        		String headerToken = request.getHeader("app-token");
        		long timestamp=new Long(headerTime).longValue();
        		Date datenow=new Date();
        		long thisTime=datenow.getTime();
        		if(timestamp+24*3600*1000<thisTime){
        			//tokenResult.put("error", "time error");
        			this.writeToResponse(JSON.toJSONString(tokenResult),response);
        			return false;
        		}
        		if(!MD5Util.md5(request.getParameter("data")+loginUser.getToken()+timestamp).toLowerCase().equals(headerToken)){
        			//tokenResult.put("error", "token error");
        			this.writeToResponse(JSON.toJSONString(tokenResult),response);
        			return false;
        		}
        	}
        	//动态token校验结束----------------------------------------------------------------
            
            
        	
        	//权限验证----------------
            
            //获取全部数据权限
        	Map permissionsData=adminMenuService.getPermissionsData();
        	
        	//公共权限验证(公共权限无需登录)
        	Map publicPermissions=(Map)((Map)permissionsData.get("publicPermissions")).get("actions");
        	
        	
        	
        	
        	
        	if(publicPermissions.get(controllerName)!=null){
        		List methodList=(List)publicPermissions.get(controllerName);
        		if(methodList.contains(method)){
        			return true;
        		}
        	}
        	
        	if(loginUser==null) {	
        		return loginErrorMsg(request,response);
    		}
        	
        	
        	
        	Map permissions=loginUser.getPermissions();
        	
        	
        	//log.info(JSON.toJSONString(permissionsData));
        	
        	
        	//如果具备超级管理员权限,直接通过
        	if(permissions.get("root")!=null){
        		return true;
        	}
        	
        	
        	
        	//如果是登录后的通用权限，直接通过
    		Map commonPermissions=(Map)((Map)permissionsData.get("commonPermissions")).get("actions");
    		if(commonPermissions.get(controllerName)!=null){
        		List methodList=(List)commonPermissions.get(controllerName);
        		if(methodList.contains(method)){
        			return true;
        		}
        	}
    		
    		//模块权限验证,这里不验证栏目权限，栏目权限后期在个控制器中根据业务单独封装
    		Map userActions=loginUser.getActions();
    		
    		//log.info(JSON.toJSONString(userActions));
    		
    		
    		if(userActions!=null){
    			List methodList=(List)userActions.get(controllerName);
    			if(methodList==null){
        			return permissionErrorMsg(request,response);
    			}else{
            		if(!methodList.contains(method)){
            			return permissionErrorMsg(request,response);
            		}
    			}	
    		}
        	
        	//权限验证结束---------------------
        	
        	//获取url模板参数的方法
        	//NativeWebRequest webRequest = new ServletWebRequest(request);
        	//Map<String, String> uriTemplateVars = (Map<String, String>) webRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        	//LogTool.print(uriTemplateVars, this.getClass());	
        }     
        return true;	
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		
	}
	
	
	
	
	private boolean loginErrorMsg(HttpServletRequest request,HttpServletResponse response) {
		if(request.getParameter("callback")!=null){
			String callback=WebUtil.getCallbackFunName(request.getParameter("callback"));
			this.writeToResponse(callback+"({\"result\":-1,\"msg\":\"请先登录\"})",response);
		}else if(request.getParameter("redirectUrl")!=null){
			this.writeToResponse("<script>location.href='login.html';</script>",response);
		}else{
			this.writeToResponse("{\"result\":-1,\"msg\":\"请先登录\"}",response);
		}
		return false;
	}
	
	private boolean permissionErrorMsg(HttpServletRequest request,HttpServletResponse response) {
		if(request.getParameter("callback")!=null){
			String callback=WebUtil.getCallbackFunName(request.getParameter("callback"));
			this.writeToResponse(callback+"({\"result\":-2,\"msg\":\"没有操作权限\"})",response);
		}else if(request.getParameter("redirectUrl")!=null){
			this.writeToResponse("<script>alert('没有操作权限');</script>",response);
		}else{
			this.writeToResponse("{\"result\":-2,\"msg\":\"没有操作权限\"}",response);
		}
		return false;
	}
	
}
